package org.light.verb;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;

import org.light.core.Verb;
import org.light.core.Writeable;
import org.light.domain.Domain;
import org.light.domain.Dropdown;
import org.light.domain.Field;
import org.light.domain.JavascriptBlock;
import org.light.domain.JavascriptMethod;
import org.light.domain.Method;
import org.light.domain.Signature;
import org.light.domain.Statement;
import org.light.domain.StatementList;
import org.light.domain.Type;
import org.light.easyui.EasyUIPositions;
import org.light.exception.ValidateException;
import org.light.utils.DomainUtil;
import org.light.utils.StringUtil;
import org.light.utils.WriteableUtil;

public class FilterExcel extends Verb implements EasyUIPositions {
	protected SearchByFields search = new SearchByFields();

	@Override
	public Method generateDaoImplMethod() throws Exception{
		return null;
	}
	@Override
	public Method generateDaoMethodDefinition()  throws Exception{
		return null;
	}
	@Override
	public Method generateServiceMethodDefinition()  throws Exception{
		return null;
	}
	@Override
	public Method generateServiceImplMethod()  throws Exception{
		return null;
	}

	public FilterExcel(){
		super();
		this.setLabel("Excel过滤");
	}
	
	public FilterExcel(Domain domain) throws ValidateException{
		super();
		this.domain = domain;
		this.denied = domain.isVerbDenied("FilterExcel");
		this.search = new SearchByFields(domain);
		this.setVerbName("Filter"+StringUtil.capFirst(this.domain.getPlural())+"Excel");
		this.setLabel("Excel过滤");
		if  (domain.getLanguage().equalsIgnoreCase("english"))  this.setLabel("FilterExcel");
	}

	@Override
	public Method generateControllerMethod()  throws Exception{
		if (this.denied)
			return null;
		else {
			this.search.setDomain(this.domain);		
			Method method = new Method();
			method.setStandardName(this.getVerbName());
			method.addSignature(new Signature(1, "Query("+this.domain.getSnakeDomainName()+"_query_request)","Query<"+this.domain.getCapFirstDomainName()+"QueryRequest>"));
			method.setReturnType(new Type("Response<Full<Bytes>>"));
			method.addAdditionalImport("std::fs");
			method.addAdditionalImport("crate::utils::excel_util::export_excel_workbook_with_image");
			
			Set<Domain> dropdownDomainSet = new TreeSet<>();
			for (Field f: this.domain.getPlainFields()) {
				if (f instanceof Dropdown) {
					Dropdown dp = (Dropdown) f;
					dropdownDomainSet.add(dp.getTarget());
				}
			}
			
			for (Domain d:dropdownDomainSet) {
				FindById find = new FindById(d);
				method.addAdditionalImport("crate::"+StringUtil.getSnakeName(d.getServiceimplSuffix())+"::"+d.getSnakeDomainName()+"_service::"+StringUtil.getSnakeName(find.getVerbName())+" as service_"+StringUtil.getSnakeName(find.getVerbName()));
			}	
			
			List<Writeable> sList = new ArrayList<Writeable>();
			SearchByFields search = new SearchByFields(this.domain);
			sList.add(new Statement(1000L,1,"let list = service_"+StringUtil.getSnakeName(search.getVerbName())+"("+this.domain.getSnakeDomainName()+"_query_request).await.unwrap();"));
			sList.add(new Statement(2000L,1,"let mut contents : Vec<Vec<String>> = Vec::new();"));
			if  (domain.getLanguage().equalsIgnoreCase("english"))  {
				sList.add(new Statement(3000L,1,"let sheet_name = \""+this.domain.getText()+" Information\".to_string();"));
			}else {
				sList.add(new Statement(3000L,1,"let sheet_name = \""+this.domain.getText()+"信息表\".to_string();"));			
			}
			sList.add(new Statement(4000L,1,"let headers = vec!["+this.domain.generateFieldLabelsArrayStringsWithoutBrackets(DomainUtil.filterDeniedFields(this.domain.getFields(), this.deniedFields))+"];"));
			sList.add(new Statement(5000L,1,"let is_images = vec!["+this.domain.generateIsImageFieldsArrayStringsWithoutBrackets(DomainUtil.filterDeniedFields(this.domain.getFields(), this.deniedFields))+"];"));
			
			sList.add(new Statement(6000L,1,"for "+this.domain.getSnakeDomainName()+" in list {"));
			long serial = 7000L;
			for (Field f:this.domain.getFields()) {
				if (!this.deniedFields.contains(f)) {
					if (f instanceof Dropdown) {
						Dropdown dp = (Dropdown)f;
						FindById findDp = new FindById(dp.getTarget());
						sList.add(new Statement(serial,2,"let " + f.getSnakeFieldName()+" = "+this.domain.getSnakeDomainName()+"."+f.getSnakeFieldName()+";"));
						sList.add(new Statement(serial+2000L,2,"let mut " + f.getSnakeFieldName()+"_name0 = \"\".to_string();"));
						sList.add(new Statement(serial+3000L,2,"if "+f.getSnakeFieldName()+" != 0 {"));
						sList.add(new Statement(serial+4000L,3,"let " + f.getSnakeFieldName()+"_type0 = service_"+StringUtil.getSnakeName(findDp.getVerbName())+"("+f.getSnakeFieldName()+").await.unwrap();"));
						sList.add(new Statement(serial+5000L,3,"if "+f.getSnakeFieldName()+"_type0."+dp.getTarget().getDomainId().getSnakeFieldName()+" != 0 {"));
						sList.add(new Statement(serial+6000L,4,f.getSnakeFieldName()+"_name0 = "+f.getSnakeFieldName()+"_type0."+dp.getTarget().getDomainName().getSnakeFieldName()+";"));
						sList.add(new Statement(serial+7000L,3,"}"));
						sList.add(new Statement(serial+8000L,2,"}"));
						serial += 9000L;
					}
				}
			}				
			sList.add(new Statement(serial,0,""));
			String sc = "let row = vec![";
			for (Field f:this.domain.getFields()) {
				if (!this.deniedFields.contains(f)) {
					if (f instanceof Dropdown) {
						Dropdown dp = (Dropdown)f;
						sc += StringUtil.getSnakeName(dp.getAliasName()) + "_name0,";
					}else if (f.getFieldType().equalsIgnoreCase("string")||f.getFieldType().equalsIgnoreCase("image")) {
						sc += this.domain.getSnakeDomainName()+"."+f.getSnakeFieldName()+",";
					} else if (f.getFieldType().equalsIgnoreCase("i64")||f.getFieldType().equalsIgnoreCase("i32")||f.getFieldType().equalsIgnoreCase("f64")||
							f.getFieldType().equalsIgnoreCase("f32")||f.getFieldType().equalsIgnoreCase("bool")) {
						sc += this.domain.getSnakeDomainName()+"."+f.getSnakeFieldName()+".to_string(),";
					}
				}
			}
			if (this.domain.getFields()!=null && this.domain.getFields().size()>0) {
				sc = sc.substring(0,sc.length()-1);
			}
			sc += "];";
			sList.add(new Statement(serial+18000L,2,sc));
			sList.add(new Statement(serial+18000L,2,"contents.push(row);"));
			sList.add(new Statement(serial+19000L,1,"}"));
			sList.add(new Statement(serial+20000L,0,""));
			
			sList.add(new Statement(serial+21000L,1,"let full_file_path = \"./template/temp/"+this.domain.getLowerFirstPlural()+".xlsx\";"));
			sList.add(new Statement(serial+22000L,1,"export_excel_workbook_with_image(full_file_path.to_string(),sheet_name, headers, contents, is_images);"));
			sList.add(new Statement(serial+23000L,1,""));
			sList.add(new Statement(serial+24000L,1,""));
			sList.add(new Statement(serial+25000L,1,"let data = fs::read(full_file_path).unwrap();"));
			sList.add(new Statement(serial+26000L,1,"fs::remove_file(full_file_path);"));
			sList.add(new Statement(serial+27000L,0,""));
			sList.add(new Statement(serial+28000L,1,"Response::builder()"));
			sList.add(new Statement(serial+29000L,1,".header(\"Content-Type\", \"application/octet-stream\")"));
			sList.add(new Statement(serial+30000L,1,".header(\"Content-Disposition\", \"attachment; filename="+this.domain.getLowerFirstPlural()+".xlsx\")"));
			sList.add(new Statement(serial+31000L,1,".header(\"Content-Transfer-Encoding\", \"binary\")"));
			sList.add(new Statement(serial+32000L,1,".body(Full::from(data))"));
			sList.add(new Statement(serial+33000L,1,".unwrap()"));
			method.setMethodStatementList(WriteableUtil.merge(sList));
			return method;
		}
	}
	@Override
	public JavascriptBlock generateEasyUIJSButtonBlock() throws Exception {
		return null;
	}
	@Override
	public JavascriptMethod generateEasyUIJSActionMethod() throws Exception {
		if (this.denied)
			return null;
		else {
			Domain domain = this.domain;
			JavascriptMethod method = new JavascriptMethod();
			method.setSerial(200);
			method.setStandardName("filter"+domain.getPlural()+"Excel");
					
			StatementList sl = new StatementList();
			sl.add(new Statement(1000,1, "params = {"));
			long serial = 2000;
			for (Field f: domain.getSearchFields()){
				if (f instanceof Dropdown)
					sl.add(new Statement(serial,2, f.getLowerFirstFieldName()+":$(\"#ffsearch\").find(\"#"+f.getLowerFirstFieldName()+"\").combobox(\"getValue\"),"));
				else if (!f.getFieldType().equalsIgnoreCase("bool"))
					sl.add(new Statement(serial,2, f.getLowerFirstFieldName()+":$(\"#ffsearch\").find(\"#"+f.getLowerFirstFieldName()+"\").val(),"));
				else 
					sl.add(new Statement(serial,2, f.getLowerFirstFieldName()+":parseBoolean($(\"#ffsearch\").find(\"#"+f.getLowerFirstFieldName()+"\").val()),"));
				serial+=1000;
			}	
			sl.add(new Statement(serial,1, "};"));
			sl.add(new Statement(serial+1000,1, "var params0 = $.param(params);"));
			sl.add(new Statement(serial+2000,1, "document.location.href = \"../"+this.domain.getControllerPackagePrefix()+this.domain.getLowerFirstDomainName()+domain.getControllerNamingSuffix()+"/filter"+this.domain.getCapFirstPlural()+"Excel?\" + params0;"));
		    
			method.setMethodStatementList(sl);
			return method;	
		}
	}
}
